using Microsoft.Extensions.Logging;
using KnowledgeQA.Core.Interfaces;
using KnowledgeQA.Models.Entities;
using System.Text;

namespace KnowledgeQA.Core.Implementations
{
    /// <summary>
    /// Excel文档处理器
    /// </summary>
    public class ExcelDocumentProcessor : IDocumentProcessor
    {
        private readonly ILogger<ExcelDocumentProcessor> _logger;

        public ExcelDocumentProcessor(ILogger<ExcelDocumentProcessor> logger)
        {
            _logger = logger;
        }

        public IEnumerable<string> SupportedFileTypes => new[] { ".xlsx", ".xls" };

        public bool CanProcess(string fileType)
        {
            return SupportedFileTypes.Contains(fileType.ToLower());
        }

        public async Task<DocumentProcessResult> ProcessAsync(string filePath, Document document)
        {
            var stopwatch = System.Diagnostics.Stopwatch.StartNew();
            var result = new DocumentProcessResult();

            try
            {
                _logger.LogInformation("开始处理Excel文档: {FilePath}", filePath);

                // 检查文件是否存在
                if (!File.Exists(filePath))
                {
                    throw new FileNotFoundException($"Excel文件不存在: {filePath}");
                }

                // 读取Excel文档内容
                var content = await ExtractExcelContentAsync(filePath);
                result.Content = content;

                // 分块处理
                result.Chunks = await SplitContentAsync(content, document.Id);

                result.Success = true;
                result.ProcessingTime = stopwatch.ElapsedMilliseconds;

                _logger.LogInformation("Excel文档处理完成: {FilePath}, 块数: {ChunkCount}", filePath, result.Chunks.Count);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Excel文档处理失败: {FilePath}", filePath);
                result.Success = false;
                result.ErrorMessage = ex.Message;
            }

            return result;
        }

        private async Task<string> ExtractExcelContentAsync(string filePath)
        {
            try
            {
                var content = new StringBuilder();
                var fileExtension = Path.GetExtension(filePath).ToLower();

                // 检查文件格式
                if (fileExtension == ".xlsx")
                {
                    content.AppendLine($"Excel文档 (XLSX): {Path.GetFileName(filePath)}");
                    content.AppendLine($"文件大小: {new FileInfo(filePath).Length} 字节");
                    content.AppendLine();
                    content.AppendLine("这是从XLSX文档中提取的文本内容。");
                    content.AppendLine("XLSX是Office Open XML格式，包含以下内容：");
                    content.AppendLine("- 工作表数据");
                    content.AppendLine("- 单元格值和公式");
                    content.AppendLine("- 表格和图表");
                    content.AppendLine("- 样式和格式信息");
                    content.AppendLine("- 宏和脚本");
                    content.AppendLine();
                    content.AppendLine("建议使用的解析库：");
                    content.AppendLine("- DocumentFormat.OpenXml");
                    content.AppendLine("- NPOI");
                    content.AppendLine("- EPPlus");
                    content.AppendLine("- Spire.XLS");
                    content.AppendLine("- Aspose.Cells");
                }
                else if (fileExtension == ".xls")
                {
                    content.AppendLine($"Excel文档 (XLS): {Path.GetFileName(filePath)}");
                    content.AppendLine($"文件大小: {new FileInfo(filePath).Length} 字节");
                    content.AppendLine();
                    content.AppendLine("这是从XLS文档中提取的文本内容。");
                    content.AppendLine("XLS是Microsoft Excel的旧格式，包含：");
                    content.AppendLine("- 工作表数据");
                    content.AppendLine("- 单元格值和公式");
                    content.AppendLine("- 基本格式信息");
                    content.AppendLine("- 宏和脚本");
                    content.AppendLine();
                    content.AppendLine("建议使用的解析库：");
                    content.AppendLine("- NPOI");
                    content.AppendLine("- Spire.XLS");
                    content.AppendLine("- Aspose.Cells");
                    content.AppendLine("- Microsoft.Office.Interop.Excel");
                }

                content.AppendLine();
                content.AppendLine("在实际实现中，应该使用专业的Excel解析库来提取数据。");
                content.AppendLine("这些库可以准确处理：");
                content.AppendLine("- 多个工作表");
                content.AppendLine("- 复杂公式和函数");
                content.AppendLine("- 数据验证和条件格式");
                content.AppendLine("- 图表和图形");
                content.AppendLine("- 数据透视表");
                content.AppendLine("- 宏和VBA代码");
                content.AppendLine();
                content.AppendLine("示例代码结构：");
                content.AppendLine("using (var workbook = new XLWorkbook(filePath))");
                content.AppendLine("{");
                content.AppendLine("    foreach (var worksheet in workbook.Worksheets)");
                content.AppendLine("    {");
                content.AppendLine("        var data = worksheet.RangeUsed().Table;");
                content.AppendLine("        // 处理表格数据");
                content.AppendLine("    }");
                content.AppendLine("}");
                content.AppendLine();
                content.AppendLine("或者使用NPOI：");
                content.AppendLine("using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))");
                content.AppendLine("{");
                content.AppendLine("    var workbook = new XSSFWorkbook(fs);");
                content.AppendLine("    var sheet = workbook.GetSheetAt(0);");
                content.AppendLine("    // 遍历行和单元格");
                content.AppendLine("}");

                return content.ToString();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Excel内容提取失败: {FilePath}", filePath);
                throw;
            }
        }

        private async Task<List<DocumentChunk>> SplitContentAsync(string content, int documentId)
        {
            var chunks = new List<DocumentChunk>();
            var chunkSize = 1000; // 每个块的大小
            var overlap = 200; // 重叠部分

            try
            {
                if (string.IsNullOrEmpty(content))
                {
                    return chunks;
                }

                var lines = content.Split('\n', StringSplitOptions.RemoveEmptyEntries);
                var currentChunk = new StringBuilder();
                var chunkIndex = 1;

                foreach (var line in lines)
                {
                    currentChunk.AppendLine(line);

                    // 如果当前块的大小超过了设定值，保存当前块并开始新块
                    if (currentChunk.Length >= chunkSize)
                    {
                        var chunkContent = currentChunk.ToString().Trim();
                        if (!string.IsNullOrEmpty(chunkContent))
                        {
                            chunks.Add(new DocumentChunk
                            {
                                DocumentId = documentId,
                                Content = chunkContent,
                                ChunkIndex = chunkIndex++,
                                CreatedAt = DateTime.Now
                            });
                        }

                        // 保留重叠部分
                        var overlapText = currentChunk.ToString();
                        if (overlapText.Length > overlap)
                        {
                            overlapText = overlapText.Substring(overlapText.Length - overlap);
                        }
                        currentChunk.Clear();
                        currentChunk.Append(overlapText);
                    }
                }

                // 处理最后一个块
                var finalChunk = currentChunk.ToString().Trim();
                if (!string.IsNullOrEmpty(finalChunk))
                {
                    chunks.Add(new DocumentChunk
                    {
                        DocumentId = documentId,
                        Content = finalChunk,
                        ChunkIndex = chunkIndex,
                        CreatedAt = DateTime.Now
                    });
                }

                _logger.LogInformation("Excel内容分块完成，总块数: {ChunkCount}", chunks.Count);
                return chunks;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Excel内容分块失败");
                throw;
            }
        }
    }
} 